﻿
#include "CDmLib.h"

//内存读取类
CMemLib::CMemLib()
{
	m_hMutex = CreateMutex(NULL, false, NULL);
}
CMemLib::CMemLib(DWORD pid)
{
	InitProcess(pid);
}
bool CMemLib::InitProcess(DWORD pid)
{
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
	hHeap = GetProcessHeap();
	if (!hProcess)
	{
		//创建失败
		return false;
	}
	InitOffSet();
}
CMemLib::~CMemLib()
{
	CloseHandle(hProcess);
	HeapDestroy(hHeap);
}

void  CMemLib::SetOffSetValues(int off1)
{
	WaitForSingleObject(m_hMutex, INFINITE);
	InitOffSet();
	offset[0] = off1;
}
void  CMemLib::SetOffSetValues(int off1, int off2)
{
	WaitForSingleObject(m_hMutex,INFINITE);
	InitOffSet();
	offset[0] = off1;
	offset[1] = off2;
}
void  CMemLib::SetOffSetValues(int off1, int off2, int off3)
{
	WaitForSingleObject(m_hMutex, INFINITE);
	InitOffSet();
	offset[0] = off1;
	offset[1] = off2;
	offset[2] = off3;
}
void  CMemLib::SetOffSetValues(int off1, int off2, int off3, int off4)
{
	WaitForSingleObject(m_hMutex, INFINITE);
	InitOffSet();
	offset[0] = off1;
	offset[1] = off2;
	offset[2] = off3;
	offset[3] = off4;
}
void  CMemLib::SetOffSetValues(int off1, int off2, int off3, int off4,int off5)
{
	WaitForSingleObject(m_hMutex, INFINITE);
	InitOffSet();
	offset[0] = off1;
	offset[1] = off2;
	offset[2] = off3;
	offset[3] = off4;
	offset[4] = off5;
}
void  CMemLib::SetOffSetValues(int off1, int off2, int off3, int off4, int off5,int off6)
{
	WaitForSingleObject(m_hMutex, INFINITE);
	InitOffSet();
	offset[0] = off1;
	offset[1] = off2;
	offset[2] = off3;
	offset[3] = off4;
	offset[4] = off5;
	offset[5] = off6;
}
//重载个取8字节的
bool CMemLib::GetDataFromAddress(DWORD pBase, int num, DWORD64 * word)
{
	int i,  *buff, temp;
	DWORD p = pBase;
	HANDLE process;
	MEMORY_BASIC_INFORMATION mbi;



	for (int i = 0; i < num; i++)
	{

		if (offset[i] == -1)
		{
			break;
		}
		VirtualQueryEx(hProcess, (PVOID)p, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if ((mbi.Protect&PAGE_READWRITE) && (mbi.State == MEM_COMMIT))
		{
			if (offset[i+1] == -1)//最后一次取值
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 8); //取8字节节
				//malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 8, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找

				*word = *(DWORD64 *)((BYTE *)buff);
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}
			else
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 4);
				//malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 4, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找

				p = *(DWORD *)((BYTE *)buff);
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}

		}
	}
	ReleaseMutex(m_hMutex);
	return p;
}
bool  CMemLib::GetDataFromAddress(DWORD pBase, int num, DWORD * word)
{
	int i, p = pBase, *buff, temp;
	HANDLE process;
	MEMORY_BASIC_INFORMATION mbi;
	
	

	for (int i = 0; i < num; i++)
	{
		
		if (offset[i] == -1)
		{
			break;
		}
		VirtualQueryEx(hProcess, (PVOID)p, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if ((mbi.Protect&PAGE_READWRITE) && (mbi.State == MEM_COMMIT))
		{
			buff = (int *)HeapAlloc(hHeap, NULL, 4);
			//malloc(mbi.RegionSize);

			ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 4, NULL);

			if (offset[i+1] == -1)
			{
				*word = *((DWORD *)buff);
			}
			else
			{
				p = *((DWORD *)buff);
				if (p==0)
				{
					HeapFree(hHeap, NULL, buff);
					buff = NULL;
					ReleaseMutex(m_hMutex); //多线程同步
					return false;
				}
			}

			if (*(int *)((BYTE *)buff) == 0 && pBase == 0x18E3BC)
			{
				OutputDebugStringA("内存值获取出错\n" );
			}
			HeapFree(hHeap, NULL, buff);
			buff = NULL;
		}
		else
		{
			ReleaseMutex(m_hMutex); //多线程同步
			return  false;
		}
	}
	ReleaseMutex(m_hMutex); //多线程同步
	return true;
}
bool CMemLib::GetDataFromAddress(DWORD pBase, int num, WORD * word)
{
	int i, p = pBase, *buff, temp;
	HANDLE process;
	MEMORY_BASIC_INFORMATION mbi;



	for (int i = 0; i < num; i++)
	{

		if (offset[i] == -1)
		{
			break;
		}
		VirtualQueryEx(hProcess, (PVOID)p, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if ((mbi.Protect&PAGE_READWRITE) && (mbi.State == MEM_COMMIT))
		{
			if (offset[i + 1] == -1)//最后一次取值
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 2); //取8字节节
														 //malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff,2, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找

				*word = *(WORD *)((BYTE *)buff);
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}
			else
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 4);
				//malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 4, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找
				if (*(int *)((BYTE *)buff) == 0 && i != num - 1)
				{
					HeapFree(hHeap, NULL, buff);
					buff = NULL;
					ReleaseMutex(m_hMutex); //多线程同步
					return false;
				}
				p = *((DWORD *)buff);
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}

		}
		else
		{
			ReleaseMutex(m_hMutex); //多线程同步
			return false;
		}
	}
	ReleaseMutex(m_hMutex); //多线程同步
	return true;
}
bool CMemLib::GetDataFromAddress(DWORD pBase, int num, BYTE * word)
{
	int i, p = pBase, *buff, temp;
	HANDLE process;
	MEMORY_BASIC_INFORMATION mbi;



	for (int i = 0; i < num; i++)
	{

		if (offset[i] == -1)
		{
			break;
		}
		VirtualQueryEx(hProcess, (PVOID)p, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if ((mbi.Protect&PAGE_READWRITE) && (mbi.State == MEM_COMMIT))
		{
			if (offset[i + 1] == -1)//最后一次取值
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 1); //取8字节节
														 //malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 1, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找

				*word = *((BYTE *)buff);
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}
			else
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 4);
				//malloc(mbi.RegionSize);

				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 4, NULL);
				//取出偏移里面的内容，再用TEMP做地址，继续查找
				p = *((DWORD *)buff);
				if (p == 0)
				{
					HeapFree(hHeap, NULL, buff);
					buff = NULL;
					ReleaseMutex(m_hMutex); //多线程同步
					return false;
				}
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
			}

		}
		else
		{
			ReleaseMutex(m_hMutex); //多线程同步
			return false;
		}
	}
	ReleaseMutex(m_hMutex); //多线程同步
	return true;
}
bool CMemLib::GetDataFromAddress(DWORD pBase, int num, char *str,int len)
{
	int i, p = pBase, *buff, temp;
	char *szBuff = NULL;
	HANDLE process;
	MEMORY_BASIC_INFORMATION mbi;
	for (int i = 0; i < num; i++)
	{
		if (offset[i] == -1)
		{
			break;
		}
		VirtualQueryEx(hProcess, (PVOID)p, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if ((mbi.Protect&PAGE_READWRITE) && (mbi.State == MEM_COMMIT))
		{
			
			//取出偏移里面的内容，再用TEMP做地址，继续查找
			if (i == num -1) //最后取字符串
			{
				szBuff = (char *)HeapAlloc(hHeap, NULL, len);
				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), szBuff, len, NULL);
				memset(str, 0, len);
				if (strlen(szBuff) > 0 && strlen(szBuff) < len)
				{

					//sprintf_s(str, strlen(szBuff), "%s", szBuff);
					memcpy_s(str, strlen(szBuff), szBuff, strlen(szBuff));
				}
				if (!szBuff)
				{
					HeapFree(hHeap, NULL, szBuff);
				}
				
			}
			else
			{
				buff = (int *)HeapAlloc(hHeap, NULL, 4);
				ReadProcessMemory(hProcess, (LPVOID)(p + offset[i]), buff, 4, NULL);
				p = *((DWORD *)buff);
				if (p == 0)
				{
					HeapFree(hHeap, NULL, buff);
					buff = NULL;
					ReleaseMutex(m_hMutex); //多线程同步
					return false;
				}
				HeapFree(hHeap, NULL, buff);
				buff = NULL;
				
			}
			
			
			
		}
		else
		{
			ReleaseMutex(m_hMutex); //多线程同步
			return false;
		}
	}
	ReleaseMutex(m_hMutex); //多线程同步
	return true;
}
void CMemLib::InitOffSet()
{
	for (int i = 0; i < 10; i++)
	{
		offset[i] = -1;
	}
}


//////////////////////////////////////////////////////////////////////////
CDmLib::CDmLib()
{
	m_dm = GetDmbject();
	m_hwnd = NULL;
}
CDmLib::~CDmLib()
{
	 m_dm->UnBindWindow();
}

int CDmLib::BindWindow() //窗口绑定
{
	return m_dm->BindWindow((long)m_hwnd, "normal", "normal", "normal", 0);//最 普通的前台模式由基类实现
}


int CDmLib::UnBinWindow() //解绑
{
	return m_dm->UnBindWindow();
}
void CDmLib::ActiveWindowStatus()
{
	if (m_dm->GetWindowState((LONG)m_hwnd, 3))
	{
		m_dm->SetWindowState((LONG)m_hwnd, 1);
	}
	Sleep(200);
}

int CDmLib::SetHwnd(HWND h1) //设置主窗口句柄
{
	m_hwnd = h1;
	return BindWindow();  //取得句柄时就绑定窗口
	
}
void CDmLib::InitSet()
{
	//获取当前目录
	_getcwd(m_path, MAX_PATH);
	m_dm->SetPath(m_path);
	m_dm->SetDict(0, "神途.txt");
	m_dm->UseDict(0);//默认使用0号字库cc
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////

//CSt * CSt::pThis = NULL;
CSt::CSt(HWND h)
{
	m_hwnd = h;
	if (!BindWindow())
	{
		DebgView("绑定窗口失败!");
		exit(1);
		return;
	}
	
}
CSt::CSt(char *cname, char * title)
{
	m_hwnd = FindWindowA(cname, title);
	DWORD pId = 0;
	GetWindowThreadProcessId(FindWindowA(cname, title), &pId);
	mem.InitProcess(pId);
	//mem = CMemLib(pId);
	mouseEvent = CreateMutex(NULL,false,NULL);
	if (m_hwnd)
	{
		if (!BindWindow())
		{
			DebgView("窗口未正确指定!");
			MessageBoxA(0, "游戏窗口未正确获取，请检查名字", "test", MB_OK);
			return;
		}
		InitSet(); //初始化
	}
	hPlug = FindWindowA("StPlug", "神途");
	if (!hPlug)
	{
		DebgView("注入插件未初始化成功!");
		return;
	}
	
	allPickingup = 0;
}
int CSt::BindWindow() //窗口绑定
{
	if (!m_hwnd)
	{
		DebgView("窗口未正确指定!");
		return 0;
	}
	ActiveWindowStatus();
	return m_dm->BindWindow((long)m_hwnd, "dx2", "windows", "windows", 0);//最 普通的前台模式由基类实现
}
int CSt::MoveToClick(int x, int y)
{
	
	
	m_dm->MoveTo(x, y);
	Sleep(20);
	return m_dm->LeftClick();
}

// DWORD WINAPI CSt::MoveThread(__in  PVOID lpParameter)//动态移动管理，发现新的坐标后即往新的移动，不负责是否到位置
// { //移动线程，专门用来调用移动函数
// 	CSt *st = (CSt *)lpParameter;
// 	do 
// 	{
// 
// 		while (st->moveAddress.X > 0 && st->moveAddress.Y > 0) //需要进行移动任务
// 		{
// 			st->MoveToGamePoin(st->moveAddress.X, st->moveAddress.Y);
// 			st->moveAddress.X = 0;
// 			st->moveAddress.Y = 0;
// 			break; //移动任务执行后就退出循环，等待新的命令，不管有没有到达，由负责调用移动的对象负责检查有没有到达，没有到达可重新执行
// 		}
// 		//st->GetCurPos(); //不断更新当前坐标
// 		Sleep(200);
// 	} while (1);
// 
// 
// 	return 0;
// }

void CSt::GameAutoMove(int x, int y)
{
	if (!m_movePosFlat)
	{
		//发送游戏窗口句柄给注入插件
		//SendMessageA(hPlug, 0x501, (WPARAM)m_hwnd, MAKELPARAM(968, 75));
		MoveToClick(968, 75);
		DebgView("发送寻路定位标记给插件！\n");
		Sleep(500);
		m_movePosFlat = true;
	}
	SendMessageA(hPlug, 0x500, NULL, MAKELPARAM(x, y));
}
// bool CSt::MoveToGamePoin(int x, int y)
// {
// 	
// 	GameAutoMove(x, y);
// 
// 	return true;
// 	GetCurPos();
// 	//计算当前坐标与目标坐标的关系并运算,看是在屏莫中的哪个格子上
// 
// 	if (x > m_infoMap.poinGameFromBig.x || y > m_infoMap.poinGameFromBig.y)
// 	{
// 		DebgView("目标坐标不正确，请修正，超出当前地图最大范围");
// 		return false;
// 	}
// 	if (abs(x - m_pointrole.x) > 10 || abs(y - m_pointrole.y) > 10)
// 	{
// 		DebgView("目标坐标不在本屏幕内，使用大地图行走..");
// 		//使用大地图行走
// 
// 		GameMoveFromBigMap(x, y);
// 
// 	}
// 	else if (/*指定格子的小地图偏移超出最大范围时，使用大地图*/abs(x - m_pointrole.x) * m_infoMap.miniMapRatioX > 53 || abs(y - m_pointrole.y) * m_infoMap.miniMapRatioY > 49)
// 	{
// 		GameMoveFromBigMap(x, y);
// 	}
// 	else
// 	{
// 		//使用小地图行走
// 		GameMoveFromMiniMap(x, y);
// 	}
// 
// 
// 
// 	return true;
// 
// }
//检查有没有到达目标的代码，暂时不用
// do
// {
// 	GetCurPos();
// 	//要不断修正坐标与小地图的对应偏移3
// 	DebgView("向目标移动中!");
// 	if (abs(m_pointrole.x - x) < 3 && abs(m_pointrole.y - y) < 3)
// 	{
// 		DebgView("已经到达目标地址!");
// 		return true;
// 	}
// 	else
// 	{
// 		if (m_pointrole.x == crLast.X && m_pointrole.y == crLast.Y)
// 		{
// 			BigMapWindow(1);
// 			MoveToClick(x1 + 95, y1 + 169);
// 			BigMapWindow(0);
// 		}
// 		else
// 		{
// 			crLast.X = m_pointrole.x;
// 			crLast.Y = m_pointrole.y;
// 		}
// 	}
// 	Sleep(500);
// } while (1);


//获取当前所在地图，并更新坐标信息
void CSt::GetCurPos()
{
	size_t i = 0;
	size_t size = 0;
	//先获取右上角的当前地图名，，
	//需获取窗口的宽度
	// 

	std::string  dm_str;
	//检查窗口状态
	//图色方式获取当前人物地图和坐标
// 	ActiveWindowStatus();
// 	dm_str = m_dm->Ocr(width.lVal - 112,3,width.lVal,  23,"FFFFFF-000000",1.0);
// 	if (dm_str.size() == 0)
// 	{
// 		DebgView("地图名未正确获取！");
// 		return;	
// 	}
// 	sprintf_s(m_infoMap.szMapName, 50, "%s", dm_str.c_str());
// 	
// 
// 	//再以地图名。从左下角去找当前坐标,
// 
// 	//识别到的是地图名 + 坐标，需去除地图名
// 	ActiveWindowStatus();
// 	dm_str = m_dm->Ocr(5, height.lVal  - 22, 190, height.lVal - 1, "FFFFFF-000000",1.0);
// 	size = dm_str.size();
// 	if (size == 0)
// 	{
// 		DebgView("地图坐标未正确识别！");
// 		return;
// 	}
// 	if (dm_str.find(m_infoMap.szMapName) == std::string::npos)
// 	{
// 		DebgView("地图识别错误！");
// 		return;
// 	}
// 	std::string strPos;
// 	i = dm_str.size();
// 	strPos = dm_str.substr(strlen(m_infoMap.szMapName),i);
// 	
// 	if (strPos.size() == 0)
// 	{
// 		DebgView("地图坐标未正确分割！");
// 		return;
// 	}
// 	i = strPos.find(":");
// 	if (i > 0)
// 	{
// 		m_pointrole.x = atoi(strPos.substr(0, i).c_str());
// 		m_pointrole.y = atoi(strPos.substr(i + 1, size - i - 1).c_str());
// 	}
		 //，内存方式获取当前地图名和坐标
		 //测试用，先获取玩家自身的位置
	DWORD x1 = 0, y1 = 0;


	do 
	{
		mem.SetOffSetValues(0, 0xc0);

		mem.GetDataFromAddress(0x18E3BC, 2, &x1);
		mem.SetOffSetValues(0, 0xc4);
		mem.GetDataFromAddress(0x18E3BC, 2, &y1);
	} while (x1 == 0 || y1 == 0 || x1 > 800 || y1 > 800);

	mem.SetOffSetValues(0, 0x13c);
	mem.GetDataFromAddress(0x33b98bc, 2, m_infoMap.szMapName, 28);//读地图名
	m_pointrole.y = y1;
	m_pointrole.x = x1;

	int gx = PGAMEW / 2;
	int gy = PGAMEH / 2;
	//把屏幕坐标对应的游戏坐标全部更新
	for (int y = 0; y < PGAMEH; y++)
	{

		//第10行
		gx = PGAMEW / 2;
		for (int x = 0; x < PGAMEW; x++)
		{

			//格子的游戏坐标偏移
			m_infoScreen[x][y].pGame.x = m_pointrole.x - gx;
			m_infoScreen[x][y].pGame.y = m_pointrole.y - gy;
			gx--;
		}
		gy--;
	}
	
}

//扫描屏幕上的血条，并记录下
void CSt::ScanBars()
{
	//找字，找血条，找第一个格子左上角开始，最后一个格子右下角开始
	//扫描到后，按标准存放当前屏幕所有格子信息中
	//扫描血条开始的时候先要等待鼠标事件，是否可以使用了。
	// 
	
	std::string dm_str;
	int x1 = m_infoScreen[0][0].healthBars.pMin.x;
	int y1 = m_infoScreen[0][0].healthBars.pMin.y;
	if (y1 < 0)
	{
		y1 = 0;
	}
	int x2 = m_infoScreen[20][20].healthBars.pMax.x;
	int y2 = m_infoScreen[20][20].healthBars.pMax.y;
	dm_str = m_dm->FindStrFastEx(x1,y1,x2,y2,"血条|血条2","110808-050505",1.0);
	std::vector<char *> buf;
	DWORD dwLen = 0;

	int x = 0;
	int y = 0;
	int i = 0;
	bool bOk = false;

	VARIANT intX, intY;
	intX.vt = VT_I4;
	intY.vt = VT_I4;

	std::vector<char *> szID;

	SplitStr(szMonsterName.c_str(), "|", &szID, &dwLen); //用ID对应物品名字，取出来存入
	if (szID.size() == 0)
	{
		DebgView("怪物文件不存在!");
		return;
	}
	if (SplitStr(dm_str.c_str(),"|",&buf,&dwLen))
	{
		for (std::vector<char *>::iterator iter = buf.begin(); iter != buf.end(); iter ++)
		{
			bOk = false;
			std::vector<char *> buf2;
			if (SplitStr((*iter),",",&buf2,&dwLen))
			{
				i = 0;
				x = atoi(buf2[1]);
				y = atoi(buf2[2]);
				for (int i = 0 ; i < buf2.size(); i++)
				{
					delete[](buf2[i]);
				}

			}
			//循环到屏幕数组中找是哪个格子，并保存
			for (int n = 0; n < PGAMEH; n++)
			{

				for (int m = 0; m < PGAMEW; m++)
				{
					if (x > m_infoScreen[n][m].healthBars.pMin.x && x < m_infoScreen[n][m].healthBars.pMax.x)
					{
						if (y > m_infoScreen[n][m].healthBars.pMin.y && y < m_infoScreen[n][m].healthBars.pMax.y)
						{
							//这个怪就是这个格子里面的，保存一下
							m_infoScreen[n][m].flag = 0; //这个是怪,假设是怪，有可能是人，可以用鼠标再去扫一次取名字
							m_infoScreen[n][m].bars.x = x;
							m_infoScreen[n][m].bars.y = y;
							//鼠标移过去识别下怪物名,如不在库则不存为一只怪，不管他
							WaitForSingleObject(mouseEvent, INFINITE);
							m_dm->MoveTo(x + 16, y + 55);//鼠标移动过去并识别

							Sleep(100);
							m_dm->Capture(x - 15, y + 30, x + 32 + 15, y + 37 + 35, "xxx.bmp");
							int  id = m_dm->FindStrFast(x - 15, y + 30, x + 32 + 15, y + 37 + 325, szMonsterName.c_str(),szMonsterColor.c_str(),1.0,&intX,&intY);
							if (id > -1)
							{
								m_infoScreen[n][m].flag = 2; //这个是怪
								std::cout << "坐标:" << m_infoScreen[n][m].pGame.x << "," << m_infoScreen[n][m].pGame.y << "有怪:   " << szID[id] << std::endl;;
								//sprintf_s(m_infoScreen[n][m].szName, 50, "%s", szID[id]);
								m_infoScreen[n][m].pMousePos.x = x + 16;
								m_infoScreen[n][m].pMousePos.y = y + 16;
							}
							else
							{
								std::cout << "坐标:" << m_infoScreen[n][m].pGame.x << "," << m_infoScreen[n][m].pGame.y << "有怪:   " << "未知怪" << std::endl;;
								//sprintf_s(m_infoScreen[n][m].szName, 50, "%s","未知怪");
							}
							ReleaseMutex(mouseEvent);
							bOk = true;
							break;
							
						}
						
					}
					else
					{
						break;
					}
				}
				if (bOk)
				{
					break; //已经成功保存上，准备第二个坐标
				}
			}
			delete[](*iter);
		}
	}
	
}
//扫描屏幕内怪物信息
void CSt::ScanMonsters()
{
	std::vector<ROLE_OBJECT> c;
	std::vector<ROLE_OBJECT> o;
	DWORD base = 0x0400000 + 0x02FBB9E0; //基地址
	DWORD p = NULL;

	POINT crTemp = { 0,0 }; //自身的坐标

	ROLE_OBJECT roleTemp;
	
	//每次查询都保存一次曾经存在过数据的基地址，以方便下次直接从此访问，而不用遍历整个内存
	std::vector<PBASE_ADDRESS_INFO> base_address;
	//先取得地图显示的第一个地址

	bool bOk = false;
	DWORD pTemp,pTemp2 = NULL;
	char szTemp[20] = "";

		//测试用，先扫描地上物品，再扫怪物

		Scangrounds();

		//测试用，先获取玩家自身的位置
		mem.SetOffSetValues(0, 0xc0);
		mem.GetDataFromAddress(0x18E3BC, 2,(DWORD *)&crTemp.x);
		mem.SetOffSetValues(0, 0xc4);
		mem.GetDataFromAddress(0x18E3BC, 2 ,(DWORD *) &crTemp.y);
// 		roleTemp.crds.X = 40;
// 		roleTemp.crds.Y = 20;
// 		c.push_back(roleTemp);
// 		FillConsoleOutputAttribute(hOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY, 2, roleTemp.crds, &dx);
// 		WriteConsoleOutputCharacterA(hOut, "■", 2, roleTemp.crds, &dx);
		//获取地图点基址
		mem.SetOffSetValues(0, 0x14);
		mem.GetDataFromAddress(base,2,&p);
		p += 4;
		for (int y = 0; y < PGAMEH; y++) //27行
		{
			//取出行首地址
			mem.SetOffSetValues(0);
			mem.GetDataFromAddress(p, 1,&pTemp);
			if (pTemp > 0)
			{
				//首地址不为空时说明里面是有东西的。
				for (int x = 0; x < PGAMEW; x++)//27列
				{
					//用行首地址取出每一行里面所有地址（此地址直接指向角色对象）
					mem.SetOffSetValues(4 * x,0);
				    mem.GetDataFromAddress(pTemp,2,&pTemp2);
					//再搜索每一行
					// 				
					memset(&roleTemp, 0, sizeof(ROLE_OBJECT));
					switch (pTemp2)
					{
					case PLAYER:
					case MONSTER:
					case MYHERO:
					case NPC:
						roleTemp.falg = pTemp2;
						mem.SetOffSetValues(4*x, 0XC0);
						mem.GetDataFromAddress(pTemp, 2,(DWORD *)&roleTemp.crds.x);
						if (roleTemp.crds.x <= 0)
						{
							break;
						}
						// = (x1 - cru.X) * 2 + 40;
						mem.SetOffSetValues(4 * x, 0XC4);
						mem.GetDataFromAddress(pTemp, 2,(DWORD *)&roleTemp.crds.y);
						if (roleTemp.crds.y <=0)
						{
							break;
						}
						if (abs(roleTemp.crds.x - crTemp.x) > 13 || abs(roleTemp.crds.y - crTemp.y) > 13)
						{
							continue; //不要此太远的怪
						}

						//= (y1 - cru.Y) + 20;
						mem.SetOffSetValues(4 * x, 0x114);
						mem.GetDataFromAddress(pTemp, 2,(DWORD *)&roleTemp.role_status);
						if (roleTemp.role_status < 0)
						{
							break;
						}

						mem.SetOffSetValues(4 * x, 0x1B4);
						mem.GetDataFromAddress(pTemp, 2,(DWORD *)&roleTemp.selected);
						if (roleTemp.selected < 0)
						{
							break;
						}
						mem.SetOffSetValues(4 * x, 0x108);//读角色ID
						mem.GetDataFromAddress(pTemp, 2, (DWORD *)&roleTemp.id);
						if (roleTemp.id <= 0)
						{
							break;
						}

						switch (pTemp2)
						{
						case PLAYER:
							roleTemp.npc = 5;
							mem.SetOffSetValues(4 * x, 0x1124, 0);
							mem.GetDataFromAddress(pTemp, 2, roleTemp.role_name, 100); //读玩家名字
							mem.SetOffSetValues(4 * x, 0x1140);
							mem.GetDataFromAddress(pTemp, 2, roleTemp.hero_master_name, 100);//读英雄所属的名字  xx的英雄
							break;
						case MONSTER: //怪物，没有名字显示，但如果有所属名字，那就是宠物。
							mem.SetOffSetValues(4 * x, 0x1130);
							mem.GetDataFromAddress(pTemp, 2, roleTemp.monster_master_name, 100);
							if (strlen(roleTemp.monster_master_name) >0 )
							{
								//这是个宠物
								roleTemp.npc = 3;
								//std::cout << "宠物坐标：" << roleTemp.crds.X << "," << roleTemp.crds.Y << std::endl;
							}
							else
							{
								roleTemp.npc = 1;
							}

							break;
						case MYHERO:
							mem.SetOffSetValues(4 * x, 0x1124);
							mem.GetDataFromAddress(pTemp, 2, roleTemp.role_name, 100);//读名字
							mem.SetOffSetValues(4 * x, 0x1140);
							mem.GetDataFromAddress(pTemp, 2, roleTemp.hero_master_name, 100);//读所属名字
							if (strlen(roleTemp.hero_master_name) > 0)
							{
								roleTemp.npc = 4;
							}
							else
							{
								roleTemp.npc = 5;
							}
							break;
						case NPC:
							roleTemp.npc = 6;
							break;
						default:
							break;
						}
						c.push_back(roleTemp);				
						break;
					default:
						//此格子没怪物，清空

						break;
					}
					pTemp += 4;

				}

			}


			p += 0x10;

			Sleep(2);
		}
// 		清除掉原信息中所有坐标上的怪物信息
		for (int n = 0; n < PGAMEH; n++) //旧怪链
		{
			bOk = false;
			for (int m = 0; m < PGAMEW; m++)//新怪链
			{
				memset(&(m_infoScreen[m][n].role), 0, sizeof(ROLE_OBJECT));

			}
		}	
		//直接全部先清掉，再填上最新的坐标怪物信息
		//这里只怕要做线程同步，删除的时候不能做查看
		//memset(m_infoScreen, 0, sizeof(INFO_SCREEN) * 27 * 27);//不能这么清，还有很多信息是不用处理的


		for (int j=0; j < c.size(); j ++)
		{//处理怪物
			
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.crds.x = c[j].crds.x;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.crds.y = c[j].crds.y;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.role_status = c[j].role_status;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.falg = c[j].falg;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.id = c[j].id;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.npc = c[j].npc;
			m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.selected = c[j].selected;

			memset(&m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.hero_master_name, 0, 100);
			memset(&m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.monster_master_name, 0, 100);
			memset(&m_infoScreen[c[j].crds.x - crTemp.x + 13][c[j].crds.y - crTemp.y + 13].role.role_name, 0, 100);

		}
		
		//遍历下怪物，并显示在屏幕上

}
int CSt::ScanMonstersList() //遍历符近内存,链表中拉取
{
	DWORD pBase = 0x33b98bc; //附近物品遍历的内存基址
	char szBuff[50] = "";
	int off[3] = { 0x24,0x3c,0x48};//每个链表在节构中的偏移
	DWORD pTemp, pTemp2, pBegin, result = 0;

	std::list<ROLE_OBJECT> rolelistTemp;
	ROLE_OBJECT roleTemp;
	int i = 0;
	bool bOk = false;
	for (int m = 0; m < 3 ; m++)
	{
		pBase = 0x33b98bc;
		mem.SetOffSetValues(0, off[m]); //附近玩家表
		mem.GetDataFromAddress(pBase, 2, &pBase); //链表指针
		mem.SetOffSetValues(0);
		mem.GetDataFromAddress(pBase, 1, &pBegin); //链表第一个地址

		pTemp = pBegin; //节点地址start
		pTemp2 = pTemp;//用来判断是不是尾节点end
						   //遍历链表
		while (pTemp != pBase) //一开始就=于链表指针地址，表示没东西
		{

			for (int m=0;m<1;m++)
			{
				//先取出此节点的内容,0X8为怪物对象指针在链表中的位置
				memset(&roleTemp, 0, sizeof(ROLE_OBJECT));
				//先保存怪物地址
				mem.SetOffSetValues(0x8);
				mem.GetDataFromAddress(pTemp, 1, &result);
				roleTemp.pRole = result;


				mem.SetOffSetValues(0x8, 0); //怪物基类判断
				mem.GetDataFromAddress(pTemp, 2, &result);

				roleTemp.falg = result;

				mem.SetOffSetValues(0x8, 0xc0);
				mem.GetDataFromAddress(pTemp, 2, &result);
				roleTemp.crds.x = result;

				mem.SetOffSetValues(0x8, 0xc4);
				mem.GetDataFromAddress(pTemp, 2, &result);
				roleTemp.crds.y = result;

				if (abs(roleTemp.crds.x - m_pointrole.x) > 10 ||  abs(roleTemp.crds.y - m_pointrole.y) > 10) //太远的怪不管
				{
					break;
				}

				mem.SetOffSetValues(0x8, 0x108); //怪物ID
				mem.GetDataFromAddress(pTemp, 2, &roleTemp.id);



				if (roleTemp.id > 0 && roleTemp.falg != 0 && roleTemp
					.crds.x != 0 && roleTemp.crds.y != 0)
				{
					//break; //无效
					mem.SetOffSetValues(0x8, 0x1B4); //选中状态
					mem.GetDataFromAddress(pTemp, 2, &result);
					roleTemp.selected = result;

					mem.SetOffSetValues(0x8, 0x114); //怪物贴图状态
					mem.GetDataFromAddress(pTemp, 2, &result);
					roleTemp.role_status = result;

					switch (roleTemp.falg)
					{
					case MONSTER: //怪，宠
						mem.SetOffSetValues(0x8, 0x1128); //怪物编号
						mem.GetDataFromAddress(pTemp, 2, &result);

						GetMonsterName(result, roleTemp.role_name, ROLENAMELEN);

						mem.SetOffSetValues(0x8, 0x1130); //主人名字
						result = mem.GetDataFromAddress(pTemp, 2, roleTemp.monster_master_name, ROLENAMELEN);
						if (strlen(roleTemp.monster_master_name) == 0)
						{//怪物
							roleTemp.npc = 1;
							//std::cout << "NPC 怪物 " << roleTemp.role_name << " 出现在:" << roleTemp.crds.x << "," << roleTemp.crds.y << std::endl;
						}
						else
						{//宠物
							roleTemp.npc = 3;
							//std::cout << roleTemp.monster_master_name << "的 宠物 : " << roleTemp.role_name << "出现在:" << roleTemp.crds.x << "," << roleTemp.crds.Y << std::endl;
						}
						break;
					case PLAYER: //玩家 或其他英雄
						mem.SetOffSetValues(0x8, 0x1124); //玩家名字
						mem.GetDataFromAddress(pTemp, 2, roleTemp.role_name, ROLENAMELEN);
						roleTemp.selected = result;

						mem.SetOffSetValues(0x8, 0x1150);
						mem.GetDataFromAddress(pTemp, 2, &result); //英雄所属玩家名字长度超15之后使用指针显示
						if (result > 15)
						{
							mem.SetOffSetValues(0x8, 0x1140, 0);
							result = mem.GetDataFromAddress(pTemp, 3, roleTemp.hero_master_name, ROLENAMELEN);
						}
						else
						{
							mem.SetOffSetValues(0x8, 0x1140); //主人名字
							result = mem.GetDataFromAddress(pTemp, 2, roleTemp.hero_master_name, ROLENAMELEN);
						}

						if (strlen(roleTemp.hero_master_name) == 0)
						{//玩家
							roleTemp.npc = 5;
							//std::cout << "玩家 " << roleTemp.role_name << " 出现在:" << roleTemp.crds.x << "," << roleTemp.crds.Y << std::endl;
						}
						else
						{//英雄
							roleTemp.npc = 4;
							//std::cout << roleTemp.hero_master_name <<"  "<< roleTemp.role_name << "出现在:" << roleTemp.crds.X << "," << roleTemp.crds.Y << std::endl;
						}
						break;
					case NPC://纯NPC
							 //117c有NPC名字
						mem.SetOffSetValues(0x8, 0x117c); //玩家名字
						result = mem.GetDataFromAddress(pTemp, 2, roleTemp.role_name, ROLENAMELEN);
						roleTemp.npc = 6;
						//std::cout << "NPC " << roleTemp.role_name << " 出现在:" << roleTemp.crds.X << "," << roleTemp.crds.Y << std::endl;
						break;
					case MYHERO: //自己的英雄

						mem.SetOffSetValues(0x8, 0x1124); //玩家名字
						result = mem.GetDataFromAddress(pTemp, 2, roleTemp.role_name, ROLENAMELEN);
						mem.SetOffSetValues(0x8, 0x1140); //主人名字
						result = mem.GetDataFromAddress(pTemp, 2, roleTemp.hero_master_name, ROLENAMELEN);
						//std::cout << roleTemp.hero_master_name << "  " << roleTemp.role_name << "出现在:" << roleTemp.crds.X << "," << roleTemp.crds.Y << std::endl;
						roleTemp.npc = 4;
						break;
					default:
						break;
					}
					roleTemp.pThis = (int)this;
					rolelistTemp.push_back(roleTemp); //保存此怪
				}
				else
				{
					break; //链表已经中断了，直接跳出。
				}

				

			}


			//取下一个节点的地址
			mem.SetOffSetValues(0);
			mem.GetDataFromAddress(pTemp, 1, &pTemp);
			if (pTemp == 0)
			{
				break;  //等于0时直接跳出
			}
			i++;
		}
	}

	//将临时表与固定表做对比，更新，删除，添加

	//先删除老的

	//老表
	for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); )
	{
		bOk = false;
		//临时表
		for (std::list<ROLE_OBJECT>::iterator iter2 = rolelistTemp.begin(); iter2 != rolelistTemp.end(); iter2++)
		{

			if (iter2->id == iter1->id)
			{
				//继续存在的物品，需更新下信息，《物品没有什么信息要更新的，存在时长，后期加》
				iter1->crds.x = iter2->crds.x;
				iter1->crds.y = iter2->crds.y;
				iter1->role_status = iter2->role_status;
				iter1->selected = iter2->selected;
				bOk = true;
				break;
			}
		}
		if (bOk == false)
		{
			//此物品不存在了，需删除，从老表中
			roleList.erase(iter1++);
		}
		else
		{
			iter1++;
		}


	}
	//再检查是不是要有新增物品
	bOk = false;
	//临时表
	for (std::list<ROLE_OBJECT>::iterator iter2 = rolelistTemp.begin(); iter2 != rolelistTemp.end(); iter2++)
	{
		bOk = false;
		//老表
		for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
		{

			if (iter2->id == iter1->id)
			{
				//继续存在的物品，需更新下信息，《物品没有什么信息要更新的，存在时长，后期加》
				bOk = true;
				break;
			}
		}
		if (bOk == false)
		{
			//此物品新增，需添加,往老表中添加
			roleList.push_back(*iter2);

		}


	}
	//清空临时表
	//rolelistTemp.clear();
	

	return i;
}
//遇见怪做出判断
void CSt::EncounterMonster()
{
	std::list<ROLE_OBJECT> roleTemp;
	//此处还要做个排序，把最有价值，最近的物品放在最前面。	
	
	bool bOk = false;
	do 
	{
		bOk = false;
		roleTemp = roleList;
		roleTemp.sort(&CSt::Role_sort);
		//如果最近的怪离自己只有3格时，人物停住，不要走动
		for (std::list<ROLE_OBJECT>::iterator iter1 = roleTemp.begin(); iter1 != roleTemp.end(); iter1++)
		{
			if (iter1->role_status ==9) //死怪，跳过
			{
				continue;
			}
			if (iter1->npc == 1 || iter1->npc == 2 )
			{
				if (abs(iter1->crds.x - m_pointrole.x )+ abs(iter1->crds.y - m_pointrole.y) < 10)
				{
					DebgView("附近碰到怪,别动，等英雄来杀!\n");
					GameAutoMove(m_pointrole.x, m_pointrole.y);
					bOk = true;
					break;
				}
				
			}
		}
		Sleep(1000);
	} while (bOk);//安全再走
	DebgView("附近无怪，安全！ \n");

}
bool CSt::KillMonster(int x, int y)
{
	if (m_infoScreen[x][y].flag == 2)
	{
		//有怪，要干死
		WaitForSingleObject(mouseEvent,INFINITE);
		MoveToClick(m_infoScreen[x][y].pMousePos.x, m_infoScreen[x][y].pMousePos.y);
		ReleaseMutex(mouseEvent);
		Sleep(2000);
	}
	return false;
}
void CSt::FollowRoleer(__int64 roleId, int distance)//跟随指定角色，可指定距离
{
	do 
	{
		Sleep(500);
	} while (roleList.size() == 0);
	for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
	{
		if (iter1->id == 0x41115BACD1773BE)
		{
			//移动到此ID的身边
			GameAutoMove(iter1->crds.x, iter1->crds.y - 1);
			break;
		}
	}
}

//获取寻路剩余步数
int CSt::GetRemanentStepNum()
{
	char szBuf[100] = "";
	DWORD status = 0;
	mem.SetOffSetValues(0, 0x13B0);
	mem.GetDataFromAddress(0x18E3BC, 2, &status);
	sprintf_s(szBuf, 100, "挂机点移动寻路剩余步数:%d\n", status);
	DebgView(szBuf);
	return status;
}


bool CSt::BigMapWindow(int falg)
{
	//大地图的坐标是固定不变的。
	//x = 95   y =169  wdith = 601  height = 376
	// 
	//TAB键打开大地图
	
	//检查窗口状态
	do 
	{
		ActiveWindowStatus();
		//先识别窗口是否存在

		std::string dm_str = m_dm->FindStrFastEx(747, 143, 797, 162, "鼠标坐标", "BB9977-111111", 1.0);
		if (dm_str.size() > 0)
		{
			if (falg == 1)
			{
				DebgView("世界地图打开正常");
				return TRUE;
			}
			else //需要关闭地图
			{
				m_dm->KeyPress(9);
				Sleep(300);
			}


		}
		else
		{
			if (falg == 0)
			{
				DebgView("世界地图关闭正常");
				return TRUE;
			}
			else //需要打开地图
			{
				m_dm->KeyPress(9);
				Sleep(300);
			}
		}
	} while (1);

}
//初始始化大地图信自己
bool CSt::InitBigMap()
{
	//在配置文件中没有此大地图信息时，需要初始化此地图信息，并保存到配置文件中
	GetCurPos();

	//获取地图比例。X,Y
	BigMapWindow(1);
	std::string dm_ret = m_dm->Ocr(692, 119, 800, 140, "d49533-020202", 1.0);
	
		//打开的是当前地图
		//获取大地图上最右下角的，鼠标坐标
		//
	m_dm->MoveTo(600 + 95, 375 + 169);
	Sleep(300);
	//获取鼠标坐标
	dm_ret = m_dm->Ocr(799, 144, 855, 164, "f04140-020202|ffffff-020202", 1.0);
	int i = 0;
	i = dm_ret.find(",");
	int size = 0;
	size = dm_ret.size();
	if (i > 0)
	{
		m_infoMap.poinGameFromBig.x = atoi(dm_ret.substr(0, i).c_str());
		m_infoMap.poinGameFromBig.y = atoi(dm_ret.substr(i + 1, size).c_str());
		BigMapWindow(0);
	}
	else
	{
		//坐标获取不正确。
		return false;
	}
	COORD cr = { 0 };
	//准备获取 当前地图的小地图偏移
/*	srand((unsigned)time(NULL));*/
	//获取X的偏移
	for (int i = -1;i < 30; i +=3)
	{
		GetCurPos();
		MoveToClick(i + m_MapPos.x, m_MapPos.y);
		do 
		{		
			cr.X = m_infoMap.poinTrole.x;
			cr.Y = m_infoMap.poinTrole.y;
			Sleep(100);
			GetCurPos();
		} while (cr.X != m_infoMap.poinTrole.x || cr.Y != m_infoMap.poinTrole.y );
	}
	//获取y的偏移
	for (int i = -30; i < 30; i += 3)
	{
		MoveToClick(m_MapPos.x, i + m_MapPos.y);

		do
		{
			GetCurPos();
			cr.X = m_infoMap.poinTrole.x;
			cr.Y = m_infoMap.poinTrole.y;
			Sleep(20);
			GetCurPos();
		} while (cr.X != m_infoMap.poinTrole.x && cr.Y != m_infoMap.poinTrole.y);
	}
}
//扫描地面物品并记录下信息,大漠图色
void CSt::Scangrounds()
{
	std::string dm_str;
	//从第四格开始，前面三格不在屏幕内
	int x1 = m_infoScreen[3][3].healthBars.pMin.x;
	int y1 = m_infoScreen[3][3].healthBars.pMin.y;
	if (y1 < 0)
	{
		y1 = 0;
	}
	if (x1 < 0)
	{
		x1 = 0;
	}
	DWORD dw = 0;
	std::vector<char *> szID;
	SplitStr(szGoodName_str.c_str(), "|", &szID, &dw); //用ID对应物品名字，取出来存入
	std::vector<char *> szKey;
	SplitStr(szGoodName.c_str(), "|", &szKey, &dw); //用ID对应物品名字，取出来存入

	int x2 = m_infoScreen[23][23].healthBars.pMax.x;
	int y2 = m_infoScreen[23][23].healthBars.pMax.y;
	//
	//检查窗口状态
	ActiveWindowStatus();

	for (int n = 0; n < PGAMEH; n++) //旧怪链
	{
		for (int m = 0; m < PGAMEW; m++)//新怪链
		{
			memset(&(m_infoScreen[m][n].good), 0, sizeof(GOODS_OBJECT));

		}
	}

	dm_str = m_dm->FindStrFastEx(x1, y1, x2, y2, szGoodName.c_str(), szGoodColor.c_str(), 1.0);
	if (dm_str.size() == 0)
	{
		DebgView("未发现地面物品!");
		return;
	}
	std::vector<char *> buf;

	//开始前先清空所有的物品信息


	int x = 0;
	int y = 0;//用来判断坐标
	int id = 0;
	//HDC hdc = GetDC(m_hwnd);
	SIZE s = {0};
	bool bOk = false;
	//准备将找到的物品信息记录到主数据吕
	//校准一下当前游戏坐标
	GetCurPos();

	if (SplitStr(dm_str.c_str(),"|",&buf,&dw))
	{
		for (int i = 0; i< buf.size(); i++)
		{
			std::vector<char *> temp;
			if (SplitStr(buf[i],",",&temp,&dw))
			{
				if (temp.size() > 0)
				{
					//记录物品
					id = atoi(temp[0]);
					//GetTextExtentPoint32(hdc, szID[id],strlen(szID[id]) , &s);
					x = atoi(temp[1]);
					y = atoi(temp[2]) + 20;

					//循环到屏幕数组中找是哪个格子，并保存
					bOk = false;
					for (int n = 0; n < PGAMEH; n++)
					{

						for (int m = 0; m < PGAMEW; m++)
						{
							if (x > m_infoScreen[m][n].goods.pMin.x && x < m_infoScreen[m][n].goods.pMax.x)
							{
								if (y > m_infoScreen[m][n].goods.pMin.y && y < m_infoScreen[m][n].goods.pMax.y)
								{
									//这个怪就是这个格子里面的，保存一下
									m_infoScreen[m][n].good.flag = 1;
									sprintf_s(m_infoScreen[m][n].good.ruled.goodName, 50, "%s", szID[id]);//保存物品名
									sprintf_s(m_infoScreen[m][n].good.ruled.goodNameKey, 50, "%s", szKey[id]);//保存物品名
// 									if (m_infoScreen[m][n].flag != 2 && m_infoScreen[m][n].flag != 1)
// 									{
// 										m_infoScreen[m][n].flag = 3; //这个是怪,假设是怪，有可能是人，可以用鼠标再去扫一次取名字
// 										std::cout << "坐标:" << m_infoScreen[m][n].pGame.x << "," << m_infoScreen[m][n].pGame.y << "有   " << szID[id] << std::endl;;
// 										sprintf_s(m_infoScreen[m][n].good.goods_name, 50, "%s", szID[id]);//保存物品名
// 										sprintf_s(m_infoScreen[m][n].good.goods_name, 50, "%s", szID[id]);//保存物品名
// 										
// 										//这个物品要跳过
// 									}
// 									else if (m_infoScreen[m][n].flag == 2)
// 									{
// 										m_infoScreen[m][n].flag = 5; //这个是怪,假设是怪，有可能是人，可以用鼠标再去扫一次取名字
// 										std::cout << "坐标:" << m_infoScreen[m][n].pGame.x << "," << m_infoScreen[m][n].pGame.y << "有   " << szID[id] << std::endl;;
// 										sprintf_s(m_infoScreen[m][n].szName, 50, "%s", szID[id]);//保存物品名
// 									}
// 									else if (m_infoScreen[m][n].flag == 1)
// 									{
// 										m_infoScreen[m][n].flag = 4; //这个是怪,假设是怪，有可能是人，可以用鼠标再去扫一次取名字
// 										std::cout << "坐标:" << m_infoScreen[m][n].pGame.x << "," << m_infoScreen[m][n].pGame.y << "有   " << szID[id] << std::endl;;
// 										sprintf_s(m_infoScreen[m][n].szName, 50, "%s", szID[id]);//保存物品名
// 									}
									bOk = true;
									break;
								}
							}
						}
						if (bOk)
						{
							break; //已经成功保存上，准备第二个坐标
						}
					}


				}


			}


		}




	}
	for (int i = 0; i< szID.size(); i++)
	{
		delete[](szID[i]);
	}


}


int CSt::ScangroundsFromMem()
{

	DWORD dw = 0;
	//std::vector<char *> szName;
	//SplitStr(szGoodName_str.c_str(), "|", &szName, &dw); //用ID对应物品名字，取出来存入
	//std::vector<char *> szKey;
	//SplitStr(szGoodName.c_str(), "|", &szKey, &dw); //用ID对应物品名字，取出来存入

	GOODS_OBJECT tempItem;
	std::list<GOODS_OBJECT> itemlistTemp; //临时表
	signed short int result = 0;

	signed short int  x = 0,y = 0,key =0;

	DWORD pBase, pTemp, pTemp2,pBegin;
		
	pBase = 0x33b98bc; //游戏管理器基址
	mem.SetOffSetValues(0, 0x30);
	mem.GetDataFromAddress(pBase, 2,&pBase); //链表指针
	int bOk = false;
	mem.SetOffSetValues(0);
	mem.GetDataFromAddress(pBase, 1, &pBegin); //链表第一个地址
	pTemp = pBegin; //节点地址start
					//遍历链表
	int i = 0;
	while (pTemp != pBase)
	{
		//先取出此节点的内容
		mem.SetOffSetValues(0x38);
		mem.GetDataFromAddress(pTemp, 1, tempItem.ruled.goodName, GOODSNAMELEN);

		for (int j = 0; j < m_vecGoodRules.size(); j++)
		{
			if (strcmp(m_vecGoodRules[j].goodName, tempItem.ruled.goodName) == 0 || allPickingup == 1)
			{
				//是需要捡的物品
				// 					sprintf_s(tempItem.ruled.goodNameKey, 20, "%s", m_vecGoodRules[j].goodNameKey); //存放关键字，有时候需要在控制台上显示用，无其他用
				// 					//填充此物品对应拾取的规则
				// 					tempItem.ruled.id = m_vecGoodRules[j].id;
				// 					tempItem.ruled.weight = 
				memcpy_s(&tempItem.ruled, sizeof(PICKING_UP_RULES), &m_vecGoodRules[j], sizeof(PICKING_UP_RULES));
				mem.SetOffSetValues(0x8);
				mem.GetDataFromAddress(pTemp, 1, &tempItem.id);

				mem.SetOffSetValues(0x18);
				mem.GetDataFromAddress(pTemp, 1,(WORD *)&x);

				mem.SetOffSetValues(0x1c);
				mem.GetDataFromAddress(pTemp, 1, (WORD *)&y);

				mem.SetOffSetValues(0x30);
				mem.GetDataFromAddress(pTemp, 1, (WORD *)&key);

				x = x - ((~key * 0xdee2) + 0x3871) % 0x4a4b;
				y = y - ((~key * 0xdee2) + 0x3871) % 0x4a4b;
				tempItem.point.x = x;
				tempItem.point.y = y;
				if (abs(x - m_pointrole.x) > 10 || abs(y - m_pointrole.y) > 10) //超出屏幕范围的不在拾取表中
				{
					continue;
				}
				tempItem.pThis = (int)this;
				itemlistTemp.push_back(tempItem); //加入临时表
				i++;
				break;
			}
		}
		//取下一个节点的地址
		mem.SetOffSetValues(0);
		mem.GetDataFromAddress(pTemp, 1,&pTemp);
		if (pTemp == 0 || pTemp == 0xcccccccc)
		{
			break;
		}
		//std::cout << szBuff << "出现在:" << x << "," << y << std::endl;

	}

	//将临时表与固定表做对比，更新，删除，添加

	//先删除老的

	//老表
	for (std::list<GOODS_OBJECT>::iterator iter1 = itemList.begin(); iter1 != itemList.end(); )
	{
		bOk = false;
		//临时表
		for (std::list<GOODS_OBJECT>::iterator iter2 = itemlistTemp.begin(); iter2 != itemlistTemp.end(); iter2++)
		{

			if (iter2->id == iter1->id)
			{
				//继续存在的物品，需更新下信息，《物品没有什么信息要更新的，存在时长，后期加》
				bOk = true;
				break;
			}
		}
		if (bOk == false)
		{
			//此物品不存在了，需删除，从老表中
			itemList.erase(iter1++);
		}
		else
		{
			iter1++;
		}


	}
	//再检查是不是要有新增物品
	bOk = false;
	//临时表
	for (std::list<GOODS_OBJECT>::iterator iter2 = itemlistTemp.begin(); iter2 != itemlistTemp.end(); iter2++)
	{
		bOk = false;
		//老表
		for (std::list<GOODS_OBJECT>::iterator iter1 = itemList.begin(); iter1 != itemList.end(); iter1++)
		{

			if (iter2->id == iter1->id)
			{
				//继续存在的物品，需更新下信息，《物品没有什么信息要更新的，存在时长，后期加》
				bOk = true;
				break;
			}
		}
		if (bOk == false)
		{
			//此物品新增，需添加,往老表中添加
			itemList.push_back(*iter2);

		}


	}
	//清空临时表
	//itemlistTemp.clear();


	return i;

}
//背包相关函数
int CSt::GetNumberSpaces()//获取背包剩余格子数
{
	DWORD num = 0;
	DWORD pBase = 0x1b8b778;
	mem.SetOffSetValues(0, 0xc,0x20c,0x2ec);
	mem.GetDataFromAddress(pBase, 4, &num); //链表指针
	return num;
}

//怪物LIST排序
BOOL CSt::Role_sort(const ROLE_OBJECT & node1, const ROLE_OBJECT & node2)
{
	CSt *p = (CSt *)node1.pThis;
	return abs(node1.crds.x - p->m_pointrole.x )+ abs(node1.crds.y - p->m_pointrole.y) < abs(node2.crds.x - p->m_pointrole.x )+ (node2.crds.y - p->m_pointrole.y);
}
//物品LIST排序规则
BOOL CSt::goods_sort(const _GOODS_OBJECT & node1, const _GOODS_OBJECT & node2)
{
	//物品上已经有怪物或NPC，或玩家时，此物品拾取最靠后
	CSt *p = (CSt *)node1.pThis;
	bool only1 = false;
	bool only2 = false;
	int weight1 = 0;
	int weight2 = 0;
	for (std::list<ROLE_OBJECT>::iterator iter2 = p->roleList.begin(); iter2 != p->roleList.end(); iter2++)
	{
		if (iter2->crds.x == node1.point.x && iter2->crds.y == node1.point.y)
		{
			only1 = true; //1号物品上有人
						  //break;

		}
		if (iter2->crds.x == node2.point.x && iter2->crds.y == node2.point.y)
		{
			only2 = true; //2号物品上有人
						  //break;

		}
	}

	if (only1 == true && only2 == false)  //有人的排后
	{
		return false; //1>2
	}
	if (only1 == false && only2 == true)  //有人的排后
	{
		return true; //1 < 2
	}

	if ((only1 == false && only2 == false) || (only1 == true && only2 == true))
	{
		//都有人或都没人时，使用其他判断

		//距离加权重
		weight1 = node1.ruled.weight + abs(p->m_pointrole.x - node1.point.x) + abs(p->m_pointrole.y - node1.point.y);
		weight2 = node2.ruled.weight + abs(p->m_pointrole.y - node2.point.x) + abs(p->m_pointrole.y - node2.point.y);
		if (weight1 > weight2)
		{
			return true;
		}
		else if (weight1 < weight2)

		{
			return false;
		}
		else //权重也一样时，按X小的为前，X一样时按Y小的为前
		{
			if (node1.point.x < node2.point.x)	
			{
				return true;
			}
			else if (node1.point.x > node2.point.x)
			{
				return false;
			}
			else //X一样时，按Y小的为前
			{

				if (node1.point.y < node2.point.y)
				{
					return true;
				}
				else if (node1.point.y > node2.point.y)
				{
					return false;
				}

			}
		}


	}
}

void CSt::TestApi()
{
	//设置鼠标目标

	//按技能

	m_dm->KeyPress(113);
}	

//跟随选中的角色移动,可指定间隔距离
// void CSt::FollowRoleer(int distance)
// {
// 
// 
// }

//拾取判断，重写
state_type CSt::Pickingup()//专门拾取
{
	
	bool bOk = false;
	int x, y;
	char szBuf[100] = "";
	DWORD status = 0;
	//扫描怪物列，如果出一威胁怪物，进入遭遇状态
	
	if (GetNumberSpaces() == 0)
	{
		DebgView("包包满了，需要处理\n");
		return state_FullState; 
	}
	GetCurPos(); //对比当前坐标
	if (m_GoodId > 0) //已经有物品在拾取
	{
		bOk = false;
		sprintf_s(szBuf, 100, "物品坐标: %d,%d",m_goodPoint.x, m_goodPoint.y);
		if (m_pointrole.x == m_goodPoint.x && m_pointrole.y == m_goodPoint.y)
		{
			DebgView("  到达物品上，拾取\n");
			Sleep(10);
			m_dm->KeyPress(192);
			Sleep(50);
		}
		else //在拾取中，但又未到达物品上时，可以扫描下周边怪物，
		{
			DebgView("物品拾取中！\n");
			return state_PatrolState; //进入巡逻状态
		}


		if (GetGoodsIsExist(m_GoodId))
		{
			DebgView("  物品未拾取成功，可能无法拾取，需要添加禁止，未成功\n");
		}
		else
		{
			DebgView("  此物品已经拾取成功\n");
			m_GoodId = 0; //当前没有物品拾取

		}

	}
	else //扫描地面，定位目标
	{
		itemList.sort(&CSt::goods_sort); //对物品排序，筛选，拾取最优先级那个物品,
		for (std::list<GOODS_OBJECT>::iterator iter1 = itemList.begin(); iter1 != itemList.end(); iter1++)
		{
			sprintf_s(szBuf, 100, "当前要拾取的物品是:%s, 坐标 %d,%d ", iter1->ruled.goodName, iter1->point.x, iter1->point.y);
			DebgView(szBuf);

			//设置列表中第一个物品为本轮要拾取物品
			m_GoodId = iter1->id;
			m_goodPoint.x = iter1->point.x;
			m_goodPoint.y = iter1->point.y;
			GameAutoMove(m_goodPoint.x, m_goodPoint.y);
			DebgView("移动到物品上\n");
			return state_PatrolState;

		}
			



	}
	return state_PatrolState; //进入巡逻状态

}
//巡逻判断，重写
state_type CSt::Patrol()
{
	GetCurPos();
	int patrol_type = 1;//0为随机巡逻,1为随机从指定点中选择巡逻，2为按顺序从指定点中巡逻
	int i,ii,id = 0;
	if (abs(m_pointrole.x - m_patrol_point.x ) < 5 && abs(m_pointrole.y - m_patrol_point.y) < 5)
	{
		//已经到达巡逻点了，清空巡逻坐标
		m_patrol_point.x = 0;
		m_patrol_point.y = 0;
	}

	if (m_patrol_point.x == 0 || m_patrol_point.y == 0) //没有巡逻目标
	{

		for (i = 0; i < 100; i++)
		{
			if (strcmp(aotuCoord[i].mapName, m_infoMap.szMapName) == 0)
			{
				DebgView("当前为巡逻地图\n");
				break;
			}
		}

		
		switch (patrol_type)
		{
		case 0:
			break;
		case 2:

			break;
		case 1:
			id = rand() % 12;
			m_patrol_point.x = aotuCoord[i].cr[id].X;
			m_patrol_point.y = aotuCoord[i].cr[id].Y;
			
		default:
			break;
		}
		GameAutoMove(m_patrol_point.x, m_patrol_point.y);//
		return state_PatrolState; //继续巡逻状态
	}
	else
	{
		//在巡逻中时要检查是否遇怪，是否有装备
		int iGoods = 0;
		int iMonsters = 0;
		//判断有没有怪
		iMonsters = ScanMonstersList();
		iGoods = ScangroundsFromMem();

		if (iMonsters > 0)
		{
			//如果最近的怪离自己只有3格时，人物停住，不要走动
			iMonsters = 0;
			for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
			{
				if (iter1->role_status == 9) //死怪，跳过
				{
					continue;
				}
				if (iter1->npc == 1 || iter1->npc == 2)
				{
					if (abs(iter1->crds.x - m_pointrole.x) + abs(iter1->crds.y - m_pointrole.y) < 5)  //离得近的怪直接干
					{


						DebgView("巡逻时发现怪物，有威胁，进入攻击模式\n");
						//人物需要停下来,近战的直接点，不用停
						GameAutoMove(m_pointrole.x, m_pointrole.y);//对当前坐标寻路，人会停下来
						//取消当前的巡逻地点
						m_patrol_point.x = 0;
						m_patrol_point.y = 0;
						return state_AttackState;
					}
					if (iGoods = 0)
					{
						GameAutoMove(m_pointrole.x, m_pointrole.y);//对当前坐标寻路，人会停下来
						return state_AttackState; //没物品，又发现怪，直接干

					}
				}
			}
		}

		//判断有没有掉落
		if (iGoods > 0)//扫描地面物品)
		{

			return state_PickingupState;
		}

		//最后又没物品，又没怪时才是判断人物有没有卡住
		DWORD ii = 0;
		mem.SetOffSetValues(0x0, 0x114);
		mem.GetDataFromAddress(0x18E3BC, 2, &ii);
		if (ii == 0)
		{
			DebgView("巡逻时人物未动，调用寻路CALL\n");

			GameAutoMove(m_patrol_point.x, m_patrol_point.y);
		}
		


	}
	return state_PatrolState; //继续巡逻状态

}
//遇怪判断，重写
state_type CSt::Encounter()
{
	GetCurPos();
	//判断当前遇到的怪，能不能打，能打就攻击，不能打就跑路
	bool bOk = false;
	roleList.sort(&CSt::Role_sort);
		//如果最近的怪离自己只有3格时，人物停住，不要走动
	for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
	{
		if (iter1->role_status == 9) //死怪，跳过
		{
			continue;
		}
		if (iter1->npc == 1 || iter1->npc == 2)
		{
			if (abs(iter1->crds.x - m_pointrole.x) < 8 || abs(iter1->crds.y - m_pointrole.y) < 7) //8步以内，技能范围内，屏幕内
			{
				DebgView("遇上可攻击的怪物，开始攻击\n");
				m_Selected = iter1->id; //设置要攻击的怪物
				m_SelectedPoint = iter1->crds;

				return state_AttackState;
			}

		}
	}
	return state_PatrolState;

}
//攻击判断
state_type CSt::attack()//攻击判断
{
	GetCurPos();
	char szBuf[100] = "";
	if (m_Selected>0) //已经有攻击目标
	{
		for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
		{
			if (iter1->id == m_Selected)
			{
				//判断目标血量，为0表示死了，进入拾取状态，否则放技能
				if (iter1->role_status == 9 )//死了
				{
					m_Selected = 0;
					m_SelectedPoint.x = 0;
					m_SelectedPoint.y = 0;
					OutputDebugStringA("当前攻击怪物死亡，准备拾取!\n");
					return state_PatrolState;
				}
				else
				{
					DebgView("怪物攻击中！\n");
					m_SelectedPoint.x = iter1->crds.x;
					m_SelectedPoint.y = iter1->crds.y;
					int position_type = 0;//远程职业
					DWORD ii = 0;
					mem.SetOffSetValues(0x0, 0x1194);
					mem.GetDataFromAddress(0x18E3BC, 2, &ii);

					switch (position_type)//职业类型
					{
					case  1:
						if (iter1->selected == 0)
						{
							OutputDebugStringA("对当前未锁定怪物施法！\n");
							CastSkillToRole(m_SelectedPoint, 113);//对目标放指定技能
							
						}
						else
						{
							OutputDebugStringA("对当前已锁定怪物施法！\n");
							CastSkillToRole({0,0}, 113);//对目标放指定技能
							Sleep(100);
						}
						
						break;

					case 0:
						if (ii==0)//自动攻击目标，则要再点一下，否则不用点
						{
							//CastSkillToRole(m_SelectedPoint, 0);//对目标直接点击攻击
							Autoattack(iter1->pRole);
						}
						else
						{
							
						}
						

						break;
					default:
						break;
					}
				}
				return state_PatrolState;
			}
		}

		
		//mem.SetOffSetValues(0x0, 0x10c, 0x108);
		//mem.GetDataFromAddress(0x33b98Bc, 4, &ii);

	}
	else
	{
		roleList.sort(&CSt::Role_sort);
		//如果最近的怪离自己只有3格时，人物停住，不要走动
		for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
		{
			if (iter1->role_status == 9) //死怪，跳过
			{
				continue;
			}
			if (iter1->npc == 1 || iter1->npc == 2)
			{
				sprintf_s(szBuf, 100, "指定攻击目标 > %s ,坐标: %d,%d \n", iter1->role_name, iter1->crds.x, iter1->crds.y);
				DebgView(szBuf);
				m_Selected = iter1->id; //设置要攻击的怪物,下一轮再开始攻击
				m_SelectedPoint = iter1->crds;
				return state_PatrolState;

			}
		}
	}
	return state_PatrolState;
}
//逃跑判断
state_type CSt::flee()
{

	if (m_flee_point.x == 0 && m_flee_point.y == 0)
	{
		//此处还要做个排序，把最有价值，最近的物品放在最前面。	
		for (std::list<ROLE_OBJECT>::iterator iter1 = roleList.begin(); iter1 != roleList.end(); iter1++)
		{
			if (iter1->npc == 4)
			{
				//暂时就做个逃跑，跑到英雄身边好了
				GameAutoMove(iter1->crds.x + 1, iter1->crds.y + 1);
				Sleep(1000);

			}
		}

	}
	else
	{
		return state_PatrolState;//逃跑启动后转先入为主巡逻状态
	}
	

}
//配置文件初始化
void CSt::InitConfigFile()
{
	//读取文件，并提供怪物名和物品名，杂项名
	std::vector <char *> buf;
	std::vector<char *> buf2;
	std::vector<char *> buf3;
	std::vector<char *> buf4;
	std::vector<char *> buf5;
	DWORD dw = 0;
	DWORD num = 0;
	std::string strMonsters = m_dm->ReadFile("神途怪物.txt");
	if (SplitStr(strMonsters.c_str(),"\r\n",&buf,&dw))
	{
		for (std::vector<char *>::iterator iter = buf.begin();iter != buf.end(); iter ++)
		{
			std::vector<char *> temp;
			//遍历怪物，并保存到字符串，和颜色字符串中
			if (SplitStr((*iter),"|", &temp,&dw)) //拆份出要的字符
			{
				//temp.
				if (strcmp(temp[1],"0")==0)
				{
					//这个物品不查找，跳过
					for (int i = 0; i < temp.size(); i++)
					{
						delete[]temp[i];
					}
					continue;
				}
				else
				{
					//记录怪物名和颜色
					if (szMonsterName.size() >0)
					{
						szMonsterName += "|";
					}
					szMonsterName += temp[0];
					
					if (szMonsterColor.find(temp[2]) == std::string::npos) //没有这个颜色时
					{
						if (szMonsterColor.size() > 0)
						{
							szMonsterColor += "|"; //应该判断第一个名字的时候不能用|
						}
						szMonsterColor += temp[2];
					}
					 
					//清理内存
					for (int i = 0; i < temp.size(); i++)
					{
						delete[]temp[i];
					}
					
				}
				
			}

			delete[] *iter;
		}

	}

	std::string strGoods = m_dm->ReadFile("神途物品.txt");
	PICKING_UP_RULES ruleTemp;
	num = 0;
	if (SplitStr(strGoods.c_str(), "\r\n", &buf2, &dw))
	{
		for (std::vector<char *>::iterator iter = buf2.begin(); iter != buf2.end(); iter++)
		{
			std::vector<char *> temp;
			//遍历怪物，并保存到字符串，和颜色字符串中
			if (SplitStr((*iter), "|", &temp, &dw)) //拆份出要的字符
			{
				//temp.
				if (strcmp(temp[2], "0") == 0)
				{
					//这个物品不查找，跳过
					for (int i = 0; i < temp.size(); i++)
					{
						delete[]temp[i];
					}
					continue;
				}
				else
				{
					//记录物品名和颜色
					if (szGoodName.size() > 0)
					{
						szGoodName += "|";
						szGoodName_str += "|";
					}
					sprintf_s(ruleTemp.goodColor, GOODSNAMELEN, "%s", temp[3]);
					ruleTemp.id = num;
					num++;
					ruleTemp.weight = atoi(temp[2]);
					sprintf_s(ruleTemp.goodName, GOODSNAMELEN, "%s", temp[0]);
					sprintf_s(ruleTemp.goodNameKey, GOODSNAMELEN, "%s", temp[1]);
					m_vecGoodRules.push_back(ruleTemp); //保存上
					szGoodName += temp[1];
					szGoodName_str += temp[0];
					if (szGoodColor.find(temp[3]) == std::string::npos) //没有这个颜色时
					{
						if (szGoodColor.size() > 0)
						{
							szGoodColor += "|"; //应该判断第一个名字的时候不能用|
						}
						szGoodColor += temp[3];
					}

					//清理内存
					for (int i = 0; i < temp.size(); i++)
					{
						delete[]temp[i];
					}

				}

			}

			delete[] * iter;
		}

	}
	//初始化所有地图配置信息
	std::string strMaps = m_dm->ReadFile("神途小地图.txt");
	if (strMaps.size() ==0)
	{
		DebgView("地图配置信息读取失败!");
	}
	num = 0;
	if (SplitStr(strMaps.c_str(), "\r\n", &buf3, &dw))
	{
		for (std::vector<char *>::iterator iter = buf3.begin(); iter != buf3.end(); iter++)
		{
			std::vector<char *> temp;
			//遍历地图，并保存
			if (SplitStr((*iter), "|", &temp, &dw)) //拆份出要的字符
			{
				if (temp.size() == 5)
				{
					//保存每个地图的设置
					sprintf_s(infomapfile[num].szMapName, 50, "%s", temp[0]);
					infomapfile[num].miniMapRatioX = atof(temp[1]);
					infomapfile[num].miniMapRatioY = atof(temp[2]);
					infomapfile[num].poinGameFromBig.x = atof(temp[3]);
					infomapfile[num].poinGameFromBig.y = atof(temp[4]);
				}
				
					//清理内存
				for (int i = 0; i < temp.size(); i++)
				{
					delete[]temp[i];
				}

			}
			num++;
			delete[] * iter;
		}

	}
	//初始化所有地图配置信息
	memset(aotuCoord, 0, sizeof(AOTU_COORD) * 20); //内存置0
	std::string strAuto = m_dm->ReadFile("神途挂机点.txt");
	if (strAuto.size() == 0)
	{
		DebgView("地图配置信息读取失败!\n");
	}
	num = 0;
	int num2 = 0;
	if (SplitStr(strAuto.c_str(), "\r\n", &buf4, &dw))
	{
		for (std::vector<char *>::iterator iter = buf4.begin(); iter != buf4.end(); iter++)
		{
			std::vector<char *> temp;
			//遍历地图，并保存
			
			if (SplitStr((*iter), "|", &temp, &dw)) //拆份出要的字符
			{
				if (temp.size() >1) //此地图设置有效
				{
					//先保存地图名

					sprintf_s(aotuCoord[num].mapName,MAPNAMELEN,"%s",temp[0]);
					aotuCoord[num].status = atoi(temp[1]);//保存地图状态，只有一个为激活地图
					num2 = 0;
					for (int i = 1; i < temp.size(); i ++) //每个挂机点要拆出坐标
					{
						std::vector<char *> temp2;
						if (SplitStr(temp[i], ",", &temp2, &dw)) //拆份出要的字符
						{
							if (temp2.size() == 2)
							{
								aotuCoord[num].cr[num2].X = atof(temp2[0]);
								aotuCoord[num].cr[num2].Y = atof(temp2[1]);
								num2++;
							}
							//清理内存
							for (std::vector<char *>::iterator iter = temp2.begin();iter != temp2.end();iter++)
							{
								delete[] *iter;
							}

						}
					}
				}
				else
				{
					DebgView("挂机地图无效，请检查\n");
				}

				//清理内存
				for (int i = 0; i < temp.size(); i++)
				{
					delete[]temp[i];
				}

			}
			num++;
			delete[] * iter;
		}

	}
	std::string strOthers = m_dm->ReadFile("神途杂项.txt");

}

//小地图各种偏移初始化，每次所在地图变化时需第一时间初始化
void CSt::InitMiniMap(char * szMap) //每个地图的小地图偏移量都不一样，需要实时修正,切换地图后需要调用
{
	int x, y = 0;
	//设置坐标,先写死，后面再做成自动
	//游戏坐标偏移
	int gx = 13;
	int gy = 13;
	//初始化人物固定坐标
	VARIANT width, height;
	width.vt = VT_I4;
	height.vt = VT_I4;
	if (!m_dm->GetClientSize((long)m_hwnd, &width, &height))
	{
		return;
	}

	m_MapPos.x = width.lVal - 56; //小地图坐标
	m_MapPos.y = 75;
	m_pointScreen.x = width.lVal / 2 - 16; //屏幕上人物的血条位置，位置不变，后期需自动获取。
	m_pointScreen.y = height.lVal / 2 - 32 - 74;
	m_pointSole.x = width.lVal / 2; //初始化人物脚底屏幕坐标,用来计算掉落 物品游戏坐标
	m_pointSole.y = height.lVal / 2 - 32;




	GetCurPos(); //初始化获取当前人物游戏坐标;
	float x1 = 0;
	float y1 = 0;
	bool bOk = false;
	//从配置文件中获取当前小地图的比例
	
	//当前地图的小地图领衔量
	for (int i = 0; i < 200; i++)
	{
		if (strcmp(infomapfile[i].szMapName, m_infoMap.szMapName) == 0)
		{
			//是这张地图,获取此地图的偏移，小地图的
			m_infoMap.miniMapRatioX = infomapfile[i].miniMapRatioX;
			m_infoMap.miniMapRatioY = infomapfile[i].miniMapRatioY;
			m_infoMap.poinGameFromBig.x = infomapfile[i].poinGameFromBig.x;
			m_infoMap.poinGameFromBig.y = infomapfile[i].poinGameFromBig.y;
			bOk = true;
			break;
		}

	}

	if (!bOk)
	{
		//并未获取到此大地图的偏移信息，需要初始化此大地图信息，并保存起来。
		//InitBigMap();
	}


	//510,350
	//上29，下28 左16，右16 血条长31

	if (!bOk)
	{
		DebgView("地图信息无法正确获取！请检查配置文件");
	}
	x1 = m_infoMap.miniMapRatioX;
	y1 = m_infoMap.miniMapRatioY;

	//自身血条的范围，按格子算
	int top = 28;
	int bom = 28;
	int rig = 16;
	int lef = 16;
	int len = 31;
	int hei = 4;
	//  x - 8, y - 15, x + 31 + 8, y + 14 + 4
	int barsx = 48 * 13; //计算屏幕偏移用,血条偏移,掉落 物品同样的偏移。
	int barsy = 32 * 13;

	int goodsx = 0; //计算屏幕偏移用,掉落偏移,没用上，和血条一样
	int goodsy = 0;
	//初始化小地图上偏移量
	int itempx = 0;
	int itempy = 0;
	for (y = 0; y < PGAMEH; y++)
	{

		//第10行
		gx = 13;
		barsx = 48 * 13;
		for (x = 0; x < PGAMEW; x++)
		{
			//小地图偏移

			//血条偏移，因为用了10格，所以有可能有负值，血条可能是看不到的
			m_infoScreen[x][y].healthBars.pMin.x = m_pointScreen.x - lef / 2 - barsx;
			m_infoScreen[x][y].healthBars.pMin.y = m_pointScreen.y - top / 2 - barsy;
			m_infoScreen[x][y].healthBars.pMax.x = m_pointScreen.x + rig / 2 + len - barsx;
			m_infoScreen[x][y].healthBars.pMax.y = m_pointScreen.y + bom / 2 + hei - barsy;
			//物品偏移
			m_infoScreen[x][y].goods.pMin.x = m_pointSole.x - 20 - barsx;
			m_infoScreen[x][y].goods.pMin.y = m_pointSole.y - 10 - barsy;
			m_infoScreen[x][y].goods.pMax.x = m_pointSole.x + 20 - barsx;
			m_infoScreen[x][y].goods.pMax.y = m_pointSole.y + 10 - barsy;
			

			//格子的游戏坐标偏移
			m_infoScreen[x][y].pGame.x = m_pointrole.x - gx;
			m_infoScreen[x][y].pGame.y = m_pointrole.y - gy;

			//正数向上取整，负数向下取整

			if (gx> 0)
			{
				itempx = ceil(gx*x1);
			}
			else
			{
				itempx = floor(gx*x1);
			}

			if  (gy > 0)
			{
				
				itempy = ceil(gy*y1);
			}
			else
			{
				
				itempy = floor(gy*y1);
			}
			m_infoScreen[x][y].pMiniMap.x = m_MapPos.x - itempx;
			m_infoScreen[x][y].pMiniMap.y = m_MapPos.y - itempy;
			m_infoScreen[x][y].pMousePos.x = m_pointScreen.x + lef  - barsx;
			m_infoScreen[x][y].pMousePos.y  = m_pointScreen.y + top  - barsy;
			gx--;
			barsx -= 48;

		}
		barsy -= 32;
		gy--;
	}

}
//分割字符串，并返回数组指针和个数
bool CSt::SplitStr(const char *szBuf, const char *subBuf, __out std::vector<char *> *buf, __out DWORD *num)
{

	size_t len = strlen(szBuf); //总长度
	size_t subLen = strlen(subBuf);
	DWORD inum = 0; //找到的个数
	size_t pos = 0; //字符定位
	bool isOk = true;
	char *szTemp = NULL;

	

	if (len > 0) 
	{
		for (int i = 0; i < len; i++) //按字符搜索
		{
			isOk = true;
			for (int j = 0; j < subLen; j ++)
			{//按字符比对子串与母串

				if ( i + j > len || subBuf[j] != szBuf[i + j])
				{
					isOk = false;
					break;
				}

			}
			if (isOk) //上面的比对OK，有此子串
			{
				inum++; //记录匹配成功次数
				szTemp = new char[i-pos + 2]();
				memcpy(szTemp, &szBuf[pos], i - pos);
				//strcpy_s();
				buf->push_back(szTemp); //加到动态数组中
				pos = i + subLen; //在此处被匹配成功
				//保存前面的字符串
				
			}
			

		}
		//最后还有一个字串要弄出来
		if (pos < len)
		{
			inum++; //记录匹配成功次数
			szTemp = new char[len - pos + 2]();
			memcpy(szTemp, &szBuf[pos], len - pos);
			//strcpy_s();
			buf->push_back(szTemp); //加到动态数组中
							  //保存前面的字符串
		}
		if (inum > 0)
		{
			*num = inum;
			return true;
		}
	}
	else
	{
		return false;
	}
}
void CSt::GetMonsterName(WORD id, char *szBuff, int len)
{
	int result = 0;
	DWORD pBase = 0x33b993c, p = NULL; //怪物名称列表基址要改。
	WORD temp = 0;
	BYTE temp2 = 0;
	mem.SetOffSetValues(0);
	mem.GetDataFromAddress(pBase, 1, &pBase);
	p = pBase + 0x10;
	mem.SetOffSetValues(0x4, 0x4);
	mem.GetDataFromAddress(p, 2,&p);

	while (true)
	{
		mem.SetOffSetValues(0xc);

		mem.GetDataFromAddress(p, 1, &temp);

		if (temp >= id)
		{
			//mem.SetOffSetValues(0);
			result = p;
				//mem.GetDataFromAddress(p, 1);
			mem.SetOffSetValues(0);
			mem.GetDataFromAddress(p, 1, &p);
		}
		else
		{
			mem.SetOffSetValues(0x8);
			mem.GetDataFromAddress(p, 1,&p);
		}
		mem.SetOffSetValues(0x15);
		mem.GetDataFromAddress(p, 1, &temp2);
		if ( temp2 != 0)
		{
			break;
		}


	}

	mem.SetOffSetValues(0xc);

	mem.GetDataFromAddress(result, 1, &temp);
	if (temp == id)
	{
		mem.SetOffSetValues(0x10, 2);

		mem.GetDataFromAddress(result , 2, szBuff, len);
		//std::cout << szBuff << std::endl;
	}
	else
	{
		DebgView("无法获取正确的名字");
	}


	//下面为汇编转译的
// 	ecx = [0x33bb91c] + 0x10;
// 	eax = [[ecx + 0x4] + 0x4];
// 	while (1)
// 	{
// 		if (([eax + 0xc] >= id)
// 			edx = eax;
// 		eax = [eax]
// 	}
//  else
//  {
// 	 eax = [eax + 0x8]
//  }
// 
//  if ([eax + 0x15] != 0)
// 	 break;
// 
// }
// 
// eax = [ecx + 0x4]
// 
// if ([edx + 0xc] == ID)
// {
// 	怪物名字 = [[edx + 10]]
// }
// 
// }

}
//////////////////////////////////////////////////////////////////////////

//内存有关操作
bool CSt::GetGoodsIsExist(DWORD64 goodsId)
{
	if (ScangroundsFromMem() > 0)
	{
		for (std::list<GOODS_OBJECT>::iterator iter1 = itemList.begin(); iter1 != itemList.end(); iter1++)
		{
			if (iter1->id == m_GoodId)
			{
				return true;
			}
		}

	}

	return false;
}
void CSt::Autoattack(DWORD obj)
{
	if (obj)
	{
		SendMessage(hPlug, WM_GAMEAUTOATTAC, obj, 0);
	}
	
}
void CSt::CastSkillToRole(POINT cr,int keys) //对指定坐标对象施放 技能、按键
{
	if (cr.x ==0 || cr.y == 0)
	{
		m_dm->KeyPress(keys);
		return;
	}
	
	DWORD x1, y1;
	DWORD64 ii;
	
	x1 = m_infoScreen[cr.x - m_pointrole.x + 13][cr.y- m_pointrole.y + 13].pMousePos.x;
	y1 = m_infoScreen[cr.x - m_pointrole.x + 13][cr.y - m_pointrole.y + 13].pMousePos.y;
	
	for (int i = 0; i < 10; i++)
	{
		m_dm->MoveTo(x1, y1);
		Sleep(10);
		//获取鼠标指向的对象INT
		mem.SetOffSetValues(0x0, 0x10c, 0x108);
		mem.GetDataFromAddress(0x33b98Bc, 3,&ii);
		if (ii == m_Selected) //是否为要攻击的怪
		{
			if (keys == 0)
			{
				OutputDebugStringA("对准了怪物，点击\n");
				m_dm->LeftClick();//点击鼠标,不用一直点，如果未攻击则要点击一次
			}
			else
			{
				OutputDebugStringA("对准了怪物，放技能\n");
				m_dm->KeyPress(keys);
			}
			
			break;
		}
		else
		{
			DebgView("找不准怪!\n");
			y1 += 3;
		}
		Sleep(10);
	}
	m_dm->MoveTo(1024, 768);//鼠标移出屏幕
}
void CSt::CastSkillToRole(int address, int keys)
{
	POINT cr = { 0 };
	int x1 = 0, y1 = 0;
	DWORD ii = 0;
	switch (address)
	{
	case MYHERO:
		mem.SetOffSetValues(0x0,0x24, 0x4, 0x8, 0xc0);
		mem.GetDataFromAddress(0x0400000 + 0x2fbb89c, 5,(DWORD *)&cr.x);
		mem.SetOffSetValues(0x0,0x24, 0x4, 0x8, 0xc4);
		mem.GetDataFromAddress(0x0400000 + 0x2FBB89C, 5, (DWORD *)&cr.y);

		//break;
	case MYSELF:
		//break;
		
	default:
		x1 = m_infoScreen[cr.x - m_pointrole.x + 13][cr.y - m_pointrole.y + 13].pMousePos.x;
		y1 = m_infoScreen[cr.x - m_pointrole.x + 13][cr.y - m_pointrole.y + 13].pMousePos.y;
		for (int i=0;i < 10; i++)
		{
			m_dm->MoveTo(x1, y1);
			Sleep(20);
			//获取鼠标指向的对象INT
			mem.SetOffSetValues(0x0,0x10c, 0);
			mem.GetDataFromAddress(0x0400000 + 0x2FBB89C, 3, &ii);
			if (ii == address)
			{
				m_dm->KeyPress(keys);
				break;
			}
			Sleep(300);
		}

		
		break;
	}
}
void CSt::InitSet()
{
	
	CDmLib::InitSet();



	InitConfigFile();//初始化字符串及颜色

	InitMiniMap("abc"); //各种偏移初始化
	//初始化屏幕信息记录
	//开启屏幕扫描线程，并记录
	
	moveAddress.X = 0;
	moveAddress.Y = 0;
	//::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)&CSt::ScanScreen, (LPVOID)this, NULL, NULL);
	//Sleep(500);
	//::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)&CSt::MoveThread, (LPVOID)this, NULL, NULL);
	//Sleep(1000);
}

//扫描屏幕，计算状态，生成状态，通知主控程序做具体的事
DWORD WINAPI CSt::ScanScreen(__in  PVOID lpParameter)
{
	CSt *st = (CSt *)lpParameter;
	std::cout.setf(std::ios_base::uppercase);
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD cru = { 26,13 };
	DWORD dx = 0;
	bool bOk = false;
	FillConsoleOutputAttribute(hOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY, 2, cru, &dx);
	WriteConsoleOutputCharacterA(hOut, "■", 2, cru, &dx);
	do 
	{
		
		//st->ScangroundsFromMem();
		Sleep(100);
	//	st->ScanMonstersList();

		st->GetCurPos(); //不断更新当前坐标
		

		//仅做显示用
		int att = 0;
		for (int n = 0; n < PGAMEH; n++) 
		{
			for (int m = 0; m < PGAMEW; m++)
			{
				if (m == 13 && n == 13)
				{
					continue;
				}
				cru.X = m * 2;
				cru.Y = n;
				//遍历物品表
				bOk = false;
				for (std::list<GOODS_OBJECT>::iterator iter1 = st->itemList.begin(); iter1 != st->itemList.end(); iter1++)
				{
					if (iter1->point.x == st->m_infoScreen[m][n].pGame.x && iter1->point.y == st->m_infoScreen[m][n].pGame.y)
					{

						if (iter1->id > 0)
						{
							att = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
							FillConsoleOutputAttribute(hOut, att, 2, cru, &dx);
							WriteConsoleOutputCharacterA(hOut, iter1->ruled.goodNameKey, 2, cru, &dx);
							bOk = true; //格子有东西
						}
						break;
					}
				}

				//遍历怪物表
				for (std::list<ROLE_OBJECT>::iterator iter1 = st->roleList.begin(); iter1 != st->roleList.end(); iter1++)
				{
					if (iter1->crds.x == st->m_infoScreen[m][n].pGame.x && iter1->crds.y == st->m_infoScreen[m][n].pGame.y)
					{
						if (iter1->id > 0)
						{
							//此怪在屏幕的这个位置,在控制台上显示一下
							switch (iter1->npc)
							{
							case 1:
								att = FOREGROUND_RED | FOREGROUND_INTENSITY;
								break;
							case 2:
								att = FOREGROUND_RED | FOREGROUND_INTENSITY;
								break;
							case 3:
								att = BACKGROUND_BLUE | FOREGROUND_INTENSITY;
								break;
							case 4:
								att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
								break;
							case 5:
								att = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
								break;
							case 6:
								att = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
								break;
							default:
								break;
							}
							bOk = true; //格子有东西
							FillConsoleOutputAttribute(hOut, att, 2, cru, &dx);
							if (iter1->role_status == 9)
							{
								WriteConsoleOutputCharacterA(hOut, "×", 2, cru, &dx);
							}
							else
							{
								WriteConsoleOutputCharacterA(hOut, "■", 2, cru, &dx);
							}						
						}
						break;
					}
				}
				if (!bOk) //格子没东西了，清空
				{
					att = 0;
					FillConsoleOutputAttribute(hOut, att, 2, cru, &dx);
					WriteConsoleOutputCharacterA(hOut, " ", 2, cru, &dx);
				}
			}
		}
		Sleep(100);
	} while (1);	
	return 0;
}

void CSt::DebgView(char * buf)
{
	char szBuf[MAX_PATH] = "";
	sprintf_s(szBuf, MAX_PATH, "信息: %s", buf);
	OutputDebugStringA(szBuf);
}